home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dskut / jp_du11.zip / DU.C next >
C/C++ Source or Header  |  1990-04-17  |  5KB  |  226 lines

  1. /*
  2.   du.c :  Recursive Disk Usage
  3.     Should be compiled with Microsoft C under small
  4.     memory model
  5.  
  6.  
  7.  Copyright (c) 1990 Jussi Puttonen (Internet: jpp@utu.fi)
  8.  Not derived from licensed software.
  9.  
  10.  Permission is granted to freely use, copy, modify, and redistribute
  11.  this software, provided that no attempt is made to gain profit from it,
  12.  the author is not construed to be liable for any results of using the
  13.  software, alterations are clearly marked as such, and this notice is
  14.  not modified.
  15.  */
  16.  
  17.  
  18. #include <stdio.h>
  19. #include <dos.h>
  20. #include <string.h>
  21.  
  22. #define TRUE 1
  23. #define FALSE 0
  24.  
  25. char * remove_trailing(string, ch)
  26. /* Removes the last char of string if it is equal to ch */
  27. char * string;
  28. char ch;
  29. {
  30. char * last = &string[strlen(string)-1];
  31. if (*last==ch) *last=0;
  32. return string;
  33. }
  34.  
  35. /********* Directory scanning ********/
  36.  
  37. #define FT_RDONLY 1
  38. #define FT_HIDDEN 2
  39. #define FT_SYSTEM 4
  40. #define FT_VOLUME 8
  41. #define FT_DIRECTORY 0x10
  42. #define FT_ARCHIVE 0x20
  43.  
  44. struct Dta {
  45.      char dummy[21];
  46.      char Attr;
  47.      unsigned long Time;
  48.      unsigned long Size;
  49.      char Name[12];
  50.      char dummy2[32];
  51.     };
  52.  
  53. union REGS in,out;
  54.  
  55. int attrib_mask = FT_RDONLY | FT_DIRECTORY | FT_ARCHIVE;
  56.  
  57. FindMatch(str,spec)
  58. char *str,*spec;
  59. {
  60. char s [100];
  61. sprintf(s,"%s\\%s",str, spec);
  62. in.h.ah = 0x4E;
  63. in.x.dx = (int) s;
  64. in.x.cx = attrib_mask;
  65. intdos(&in,&out); return(out.x.ax);
  66. }
  67.  
  68. FindNext(str)
  69. char *str;
  70. {
  71. in.h.ah = 0x4F; in.x.dx = (int) str;
  72. intdos(&in,&out); return(out.x.ax);
  73. }
  74.  
  75. /********* Disk Usage ********/
  76.  
  77. struct statistics {
  78.      long count;
  79.      long bytes;
  80.      };
  81.  
  82. /* Command line options */
  83. int Technical;
  84. int Depth;
  85.  
  86. char * ldfmt(i, o, index)
  87. /* Formats the long integer i to string i */
  88. long i;
  89. char * o;
  90. {
  91. if (!index) *o=0;
  92. if (index && (index % 3 == 0)) *--o = ',';
  93. *--o = i % 10 + '0';
  94. if (i/10) return ldfmt(i/10, o, index+1);
  95.     else  return o;
  96. }
  97.  
  98. print_statistics(message, s)
  99. /* Report statistics */
  100. char * message;
  101. struct statistics s;
  102. {
  103. if (Technical)
  104.     printf("%-22s: %6ld files contain %8ld bytes\n", message, s.count,s.bytes);
  105.     else {
  106.        char scount[11], sbytes[13];
  107.        printf("%-22s: %6s files contain %10s bytes\n", message,
  108.           ldfmt(s.count, &scount[10], 0),
  109.           ldfmt(s.bytes, &sbytes[12], 0));
  110.          }
  111. }
  112.  
  113. dotted(s)
  114. /* Returns true for strings . and .. */
  115. char *s;
  116. {
  117. if (*s++ != '.') return FALSE;
  118. switch (*s++)
  119.   {
  120.   case '.' : return (*s == 0);
  121.   case 0 : return TRUE;
  122.   default : return FALSE;
  123.   }
  124. }
  125.  
  126. struct statistics Dir(str,spec, dpth)
  127. char *str;
  128. char *spec;
  129. {
  130. struct Dta DTA;
  131. int OldDta;
  132. char name[60];
  133. struct statistics s = { 0,0 };
  134.  
  135. /* Get DTA */
  136. in.h.ah = 0x2F; intdos(&in,&out);
  137. OldDta = out.x.bx;
  138.  
  139. /* Set DTA */
  140. in.h.ah = 0x1A;  in.x.dx = (int) &DTA;
  141. intdos(&in,&out);
  142.  
  143. if (! FindMatch(str,spec))
  144.   do {
  145.      if (dotted(DTA.Name)) continue;
  146.      sprintf(name,"%s\\%s",str,DTA.Name);
  147.      if (DTA.Attr & FT_DIRECTORY)
  148.       {
  149.       struct statistics sr = Dir(name, spec, dpth+1);
  150.       s.count += sr.count;
  151.       s.bytes += sr.bytes;
  152.       } else
  153.       {
  154.       s.count++; s.bytes+= DTA.Size;
  155.       }
  156.      }
  157.   while (! FindNext(str));
  158.  
  159. /* Set DTA */
  160. in.h.ah = 0x1A;  in.x.dx = OldDta;
  161. intdos(&in,&out);
  162. if ((! Depth) || (dpth <= Depth)) print_statistics(str, s);
  163. return s;
  164. }
  165.  
  166. void Help()
  167. {
  168. printf("Use: du [-t] [-d#] [-a] [dirspec] ...\n\
  169.     Calculates the total size and count of the files\n\
  170.     in the given directory and it's subdirectories.\n\
  171.     Uses current directory at default. If more than\n\
  172.     one directory is given, counts also grand total.\n\
  173.     Options:\n\
  174.            -t        Technical output (Numbers are displayed\n\
  175.                       like 999999 instead of the default 999,999)\n\
  176.            -d#       Stops reporting subtotals at depth #\n\
  177.            -a        report also hidden and system files\n\
  178. ");
  179. }
  180.  
  181. void bad_options(s)
  182. char * s;
  183. {
  184. fprintf(stderr, "Bad command line option: %s\n Use \"du -h\" to get help\n", s);
  185. exit(1);
  186. }
  187.  
  188. main(argc,argv)
  189. char **argv;
  190. {
  191. int i, specs=0;
  192. struct statistics grand_total = { 0,0 };
  193. fprintf(stderr,"Disk Usage utility 1.1. Copyright 1990 Jussi Puttonen (Internet: jpp@utu.fi)\n");
  194.  
  195. for (i=1; i<argc; i++)
  196.    if (argv[i][0] == '-')
  197.       switch (argv[i][1])
  198.          {
  199.          case 't' : case 'T' : Technical = TRUE;
  200.              if (argv[i][2]) bad_options(argv[i]); break;
  201.          case 'a' : case 'A' : attrib_mask |= (FT_SYSTEM|FT_HIDDEN);
  202.              if (argv[i][2]) bad_options(argv[i]); break;
  203.          case 'h' : case 'H' : Help(); exit(0);
  204.          case 'd' : case 'D' : Depth = atoi(&argv[i][2]); break;
  205.          default : bad_options(argv[i]);
  206.          }
  207.  
  208. for (i=1; i<argc; i++)
  209.    if (argv[i][0] != '-')
  210.       {
  211.       struct statistics st = Dir(remove_trailing(argv[i], '\\'),"*.*", 1);
  212.       grand_total.count += st.count;
  213.       grand_total.bytes += st.bytes;
  214.       specs++;
  215.       }
  216.  
  217. switch (specs)
  218.      {
  219.      case 0 : Dir(".", "*.*", 1); break;
  220.      case 1 : break;
  221.      default : print_statistics("\nGrand total", grand_total);
  222.     }
  223.  
  224. return 0;
  225. }
  226.